#include "addattentionstask.h"
#include "getliveinfohelper.h"
#include "libs/base/basetype.h"
#include "libs/base/service/downloader.h"
#include "libs/core/model/attention.h"
#include "libs/core/model/attentionmodel.h"
#include "libs/core/model/liveinfo.h"
#include "libs/core/model/model.h"
#include "libs/core/model/presenter.h"
#include "libs/core/model/presentermodel.h"
#include "liverecorder.h"
#include "services/yingceservice.h"
#include "yingce.h"
#include <QJsonDocument>
#include <QJsonObject>

AddAttentionsTask::AddAttentionsTask(LiveRecorder* recorder, int platform,
                                     const QStringList& presenter_platform_ids, QObject* parent)
    : yc::Task { 0, true, int(360000 * presenter_platform_ids.size()), parent },
      recorder_(recorder),
      platform_(platform)
{
    auto pm = YingCe::instance()->model()->presenterModel();
    auto am = YingCe::instance()->model()->attentionModel();
    for (const auto& id : presenter_platform_ids) {
        if (auto p = pm->find(platform, id)) {
            if (!am->find(p->id)) {
                new_presenters_.push_back(NewPresenter { id, p->id });
            }
        } else {
            new_presenters_.push_back(NewPresenter { id, 0 });
        }
    }
}

AddAttentionsTask::~AddAttentionsTask()
{
    if (request_id_ != 0) {
        recorder_->getLiveInfoHelper()->cancel(request_id_);
        request_id_ = 0;
    }
}

void AddAttentionsTask::startImpl()
{
    QStringList ids;
    for (const auto& i : std::as_const(new_presenters_)) {
        if (i.id == 0) {
            ids.push_back(i.platform_id);
        }
    }
    if (ids.empty()) {
        pos_ = -1;
        addAttentions();
    } else {
        YingCeService::instance()->getPresenters(
                platform_, ids,
                yc::ResponseHandler(
                        this, [this](const yc::Request& request, const yc::Response& response) {
                            Q_UNUSED(request)
                            if (response.status() == yc::OK_CODE) {
                                auto pm = YingCe::instance()->model()->presenterModel();
                                yc::Presenter pr;
                                const auto ja = response.data().toArray();
                                for (const auto& i : ja) {
                                    pr = i.toObject();
                                    pm->add(pr);
                                    setNewPresenterId(pr.platform_id, pr.id);
                                }
                                // 下载头像
                                if (!pr.avatar.isEmpty()) {
                                    YingCe::instance()->downloader()->addResource(
                                            yc::DownloadResource { pr.avatar,
                                                                   QUrl { pr.avatar }.fileName() });
                                }
                                auto it = std::find_if(
                                        new_presenters_.constBegin(), new_presenters_.constEnd(),
                                        [](const NewPresenter& pr) { return pr.id == 0; });
                                if (it == new_presenters_.constEnd()) {
                                    pos_ = -1;
                                    addAttentions();
                                    return;
                                }
                            }
                            pos_ = -1;
                            addPresenter();
                        }));
    }
}

void AddAttentionsTask::addPresenter()
{
    if (++pos_ >= new_presenters_.size()) {
        addAttentions();
    } else {
        if (new_presenters_.at(pos_).id == 0) {
            request_id_ = recorder_->getLiveInfoHelper()->get(
                    platform_, new_presenters_.at(pos_).platform_id,
                    LiveHandler(this, &AddAttentionsTask::onGetLiveInfo));
        } else {
            addPresenter();
        }
    }
}

void AddAttentionsTask::onGetLiveInfo(int presenter, const QString& args)
{
    Q_UNUSED(presenter)
    request_id_ = 0;
    const auto& platform_id = new_presenters_.at(pos_).platform_id;
    if (args.isEmpty()) {
        error_ids_ += platform_id + ',';
        addPresenter();
    } else {
        const auto root = QJsonDocument::fromJson(args.toUtf8()).object();
        yc::Presenter pr { platform_, root["anchor"].toObject() };
        if (pr.platform_id.isEmpty() || pr.platform_sec_uid.isEmpty()) {
            error_ids_ += platform_id + ',';
            addPresenter();
        } else {
            const yc::LiveInfo li = yc::LiveInfo::fromJsonObject(root);
            pr.platform_id = platform_id;
            pr.audience_count = li.view_count;
            pr.status = li.status;
            pr.update_time = QDateTime::currentDateTime();
            YingCeService::instance()->addPresenter(
                    pr,
                    yc::ResponseHandler(
                            this, [this](const yc::Request& request, const yc::Response& response) {
                                Q_UNUSED(request)
                                if (response.status() == yc::OK_CODE) {
                                    const yc::Presenter pr { response.data().toObject() };
                                    YingCe::instance()->model()->presenterModel()->add(pr);
                                    new_presenters_[pos_].id = pr.id;
                                    // 下载头像
                                    if (!pr.avatar.isEmpty()) {
                                        YingCe::instance()->downloader()->addResource(
                                                yc::DownloadResource {
                                                        pr.avatar, QUrl { pr.avatar }.fileName() });
                                    }
                                } else {
                                    error_ids_ += new_presenters_.at(pos_).platform_id + ',';
                                }
                                addPresenter();
                            }));
        }
    }
}

void AddAttentionsTask::addAttentions()
{
    QList<yc::Attention> as;
    for (const auto& i : std::as_const(new_presenters_)) {
        if (i.id != 0)
            as.push_back(yc::Attention { 0, i.id, 0 });
    }
    if (as.empty()) {
        notifyFinished();
    } else {
        YingCeService::instance()->addAttentions(
                as,
                yc::ResponseHandler(
                        this, [this](const yc::Request& request, const yc::Response& response) {
                            Q_UNUSED(request)
                            if (response.status() == yc::OK_CODE) {
                                auto am = YingCe::instance()->model()->attentionModel();
                                const QJsonArray ja = response.data().toArray();
                                for (const auto& i : ja) {
                                    yc::Attention a { i.toObject() };
                                    am->add(a);
                                }
                            }
                            notifyFinished();
                        }));
    }
}

void AddAttentionsTask::setNewPresenterId(const QString& platform_id, int id)
{
    for (auto& i : new_presenters_) {
        if (i.platform_id == platform_id) {
            i.id = id;
            break;
        }
    }
}

void AddAttentionsTask::notifyFinished()
{
    if (error_ids_.isEmpty()) {
        Q_EMIT finished();
    } else {
        error_ids_.chop(1);
        Q_EMIT failed(yc::LOGIC_ERROR, tr("Failed to add those presenters(%1).").arg(error_ids_));
    }
}
